#include <string.h> 
#include <stdio.h> 

#include <avr/io.h>
#include <avr/interrupt.h>

#include <compat/deprecated.h> 

#include "BuffFifo.h"
#include "rtc.h"
#include "mail.h"
#include "i2c.h"

#define RTC_ADRESS 	0xD0 //11010000

//time trig = 1ms
#define TIME_INTERVAL_100MS 50
#define TIME_INTERVAL_500MS 250

#define TIME_RTC_INTERVAL TIME_INTERVAL_500MS
#define TIME_TRC_1S 2//1
#define TIME_TRC_3S 6//3
#define TIME_TRC_30S 60//30
#define TIME_TRC_MINUTE 120//60
#define TIME_TRC_20MIN TIME_TRC_MINUTE * 20
unsigned int time_rtc; 
unsigned int time_rtc_task;
unsigned int time_rtc_time_update;
unsigned int time_rtc_get_data;

unsigned char rtc_time[2];

#define RTC_MANAGE_BUFF 8
BUFF_DECL_FIFO(RTCManageMsgBuf,RTC_MANAGE_BUFF);

#define RTC_SERIAL_BUFF 36
BUFF_DECL_FIFO(RTCSerialMsgBuf,RTC_SERIAL_BUFF);



#define TIME_INTERVAL_INIT 1

//#define TICKRATE 50	// time 20 ms
//#define TCNT2_INIT (0xFF-((F_CPU/1024)/TICKRATE))

#define TCNT2_INIT 0

// RTC variables
static volatile struct
{
	unsigned int mili_sec;
	unsigned char second;
	unsigned char minute;
	unsigned char hour;
}
sys_rtc_time;

static volatile unsigned int rtc_timer_interval = TIME_INTERVAL_INIT;

ISR(TIMER2_OVF_vect)
{
	TCNT2 = TCNT2_INIT;
	
	//sys_rtc_time.second += 20; //20 milisec over flow
	sys_rtc_time.mili_sec += 1000; //100 milisec over flow
	
	if(sys_rtc_time.mili_sec >= 1000)
	{
		sys_rtc_time.mili_sec = 0;
		sys_rtc_time.second++;
		if(sys_rtc_time.second >= 60)
		{
		
			if(rtc_timer_interval > 0)
			{
				rtc_timer_interval--;
			}
			
			sys_rtc_time.second -= 60;
			sys_rtc_time.minute++;
			if(sys_rtc_time.minute >= 60)
			{
				sys_rtc_time.minute = 0;
				sys_rtc_time.hour++;
				if(sys_rtc_time.hour >= 24)
				{
					sys_rtc_time.hour = 0;
				}		
			}
		}		
	}
}


void RTCManageMsgSend(char *ptr, unsigned char size)
{
	unsigned char i;
	
	for(i=0;i<size;i++)
	{
		if( BuffPutFifo(RTCManageMsgBuf,*ptr++) == FIFO_ERR)
		{
			break;
		}
	}
	SendMailFifo(MANAGE_DEV,0x01,size,(char *)RTCManageMsgBuf);
	
}

void RTCSerialMsgSend(char *ptr, unsigned char size)
{
	unsigned char i;
	
	for(i=0;i<size;i++)
	{
		if( BuffPutFifo(RTCSerialMsgBuf,*ptr++) == FIFO_ERR)
		{
			break;
		}
	}
	//SendMailFifo(SERIAL_DEV,0x01,size,(char *)RTCSerialMsgBuf);
	SendMailFifo(SERIAL_DEV,0x01,i,(char *)RTCSerialMsgBuf);
	
}


							
void InitRTC( void )
{	
	// //128 (From prescaler)
	sbi(TCCR2, CS20); cbi(TCCR2, CS21); sbi(TCCR2, CS22);
	
	//1024 (From prescaler)
	//sbi(TCCR2, CS20); sbi(TCCR2, CS21); sbi(TCCR2, CS22);

	//(No prescaling
	//sbi(TCCR2, CS20); cbi(TCCR2, CS21); cbi(TCCR2, CS22);
	
	//Timer register
	TCNT2 = TCNT2_INIT;
	
	//Output Compare register
	OCR2  = 0;
	
	//Asynchronous Status set to enable
	sbi(ASSR, AS2); //
	
	//Timer/Counter Interrupt Mask
	cbi(TIMSK, OCIE2); //Compare Match Interrupt Disable
	sbi(TIMSK, TOIE2); //Overflow Interrupt Enable
				
	time_rtc = TIME_RTC_INTERVAL;
	time_rtc_task = TIME_TRC_1S;
	time_rtc_time_update = TIME_TRC_MINUTE;
	
	//time_rtc_get_data = TIME_TRC_30S;
	time_rtc_get_data = TIME_TRC_3S;
	
	memset((void *)&rtc_time,0,sizeof(rtc_time));	
	
	i2cInit();
	
	BUFF_INIT_FIFO(RTCManageMsgBuf);
	BUFF_INIT_FIFO(RTCSerialMsgBuf);
}



void TimeRTC( void )
{
	if(time_rtc > 0)
	{
		time_rtc--;
		if(time_rtc==0)
		{		
			if(time_rtc_task>0)
			{
				time_rtc_task--;
			}
			time_rtc = TIME_RTC_INTERVAL;
		}
	}
}

struct 
{
	char regAddr;
	char regData[8];
}sRTC_Register = {0x00,{0,0,0,0,0,0,0,0}};

char RTC_I2C_Read(void)
{
	sRTC_Register.regAddr = 0;
	
	i2cMasterTransferNI(RTC_ADRESS
				,1, (unsigned char *)&sRTC_Register.regAddr
				,sizeof(sRTC_Register.regData), (unsigned char *)&sRTC_Register.regData);

	if( i2cGetError() == I2C_NONE )
	{								
		return TRUE;
	}
	
	return FALSE;

}

char RTC_I2C_Write(void)
{		
	sRTC_Register.regAddr = 0;
	i2cMasterSendNI(RTC_ADRESS, sizeof(sRTC_Register), (unsigned char *)&sRTC_Register);	

    if( i2cGetError() == I2C_NONE )
	{								
		return TRUE;
	}
	
	return FALSE;

}

char rtc_write_data_flag = FALSE;
void RTCMail(unsigned char act, unsigned char size, char * pbuf)
{
	if(act==0x01)
	{
		if(size == 2)
		{
			rtc_time[0] = *(pbuf+0);
			rtc_time[1] = *(pbuf+1);
			time_rtc_time_update = TIME_TRC_MINUTE;
			rtc_write_data_flag = TRUE;			
		}
	}
}

void RTC_time_minute_update(unsigned char * t)
{
	if( ++t[1] >= 60)
	{
		t[1] = 0;
		if( ++t[0] >= 24)
		{
			t[0] = 0;
		}
	}
}

// Convert normal decimal numbers to binary coded decimal
char decToBcd(char val)
{
  return ( (val/10*16) + (val%10) );
}

// Convert binary coded decimal to normal decimal numbers
char bcdToDec(char val)
{
  return ( (val/16*10) + (val%16) );
}

char r_str[32];
char initial = FALSE;
void RTCTask( void )
{
	if(time_rtc_task==0)
	{	
		if(time_rtc_time_update > 0)
		{
			time_rtc_time_update--;
			if(time_rtc_time_update == 0)
			{
				time_rtc_time_update = TIME_TRC_MINUTE;
				RTC_time_minute_update((unsigned char *)&rtc_time);				
				RTCManageMsgSend((char *)&rtc_time,sizeof(rtc_time));
			}
		}
		
		if(time_rtc_get_data > 0)
		{
			time_rtc_get_data--;
			if(time_rtc_get_data==0)
			{
				time_rtc_get_data = TIME_TRC_20MIN;					
				if(initial == TRUE)
				{
					sRTC_Register.regData[0] &= 0x7F;
					//sRTC_Register.regData[7] |= 0x93;
					//sRTC_Register.regData[7] |= 0x90;
					
					sprintf((char *)&r_str,"RTC-W: %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x\r\n"\
							,sRTC_Register.regData[0]
							,sRTC_Register.regData[1]
							,sRTC_Register.regData[2]
							,sRTC_Register.regData[3]
							,sRTC_Register.regData[4]
							,sRTC_Register.regData[5]
							,sRTC_Register.regData[6]
							,sRTC_Register.regData[7]);
					RTCSerialMsgSend((char *)&r_str,strlen(r_str));
										
					if( RTC_I2C_Write() == TRUE )
					{
						initial = FALSE;	
					}
					time_rtc_get_data = TIME_TRC_3S;	
				}
				else if( RTC_I2C_Read() == TRUE)
				{
					sprintf((char *)&r_str,"RTC-R: %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x\r\n"\
							,sRTC_Register.regData[0]
							,sRTC_Register.regData[1]
							,sRTC_Register.regData[2]
							,sRTC_Register.regData[3]
							,sRTC_Register.regData[4]
							,sRTC_Register.regData[5]
							,sRTC_Register.regData[6]
							,sRTC_Register.regData[7]);
					RTCSerialMsgSend((char *)&r_str,strlen(r_str));
					
					// if( ((sRTC_Register.regData[0] & 0x80) == 1) 
							// || ((sRTC_Register.regData[7] & 0x80) == 0)
								// || ((sRTC_Register.regData[7] & 0x10) == 0)	)
					if( (sRTC_Register.regData[0] & 0x80) != 0) 
					{
						initial = TRUE;
						time_rtc_get_data = TIME_TRC_3S;						
					}
					else
					{
						time_rtc_time_update = bcdToDec(sRTC_Register.regData[0]) * 2;
						rtc_time[1] = bcdToDec(sRTC_Register.regData[1]);
						rtc_time[0] = bcdToDec(sRTC_Register.regData[2]);
						RTCManageMsgSend((char *)&rtc_time,sizeof(rtc_time));
					}
				}				
							
			}
		}
		
		if(rtc_write_data_flag == TRUE)
		{
			sRTC_Register.regData[1] = decToBcd(rtc_time[1]);
			sRTC_Register.regData[2] = decToBcd(rtc_time[0]);
			if( RTC_I2C_Write() == TRUE ) 
			{
				rtc_write_data_flag = FALSE;
				time_rtc_get_data = TIME_TRC_3S;
			}			
		}		
		time_rtc_task = TIME_TRC_1S;		
	}
}
